package com.wg.db.redis;

import com.wg.core.properties.PropertiesMgr;
import com.wg.core.exception.InvalidConfigException;
import com.wg.db.DbConstant;

import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Redis 实例管理器（单例）
 * 负责加载Redis配置、创建和管理多个Redis实例（支持多实例场景）
 *
 * @author 少爷123
 */
public class RedisMgr {
    private static final Log logger = LogFactory.get();
    private final Map<String, Redis> redisInstances = new ConcurrentHashMap<>();

    private RedisMgr() {
    }

    /**
     * 获取单例实例
     */
    public static RedisMgr getInstance() {
        return Singleton.INSTANCE.getManager();
    }

    /**
     * 初始化所有Redis实例（根据配置自动加载）
     */
    public void init() {
        Map<String, RedisConfig> configMap = PropertiesMgr.toMap(RedisConfig.class, DbConstant.REDIS_PREFIX);

        if (configMap == null || configMap.isEmpty()) {
            return;
        }

        for (Map.Entry<String, RedisConfig> entry : configMap.entrySet()) {
            String instanceKey = entry.getKey();
            RedisConfig config = entry.getValue();

            try {
                validateConfig(config);
                Redis redis = new Redis(config);
                redis.ping(); // 测试连接有效性
                redisInstances.put(instanceKey, redis);
                logger.info("Redis实例初始化成功 | 实例键：{}，配置：{}", instanceKey, config);
            } catch (Exception e) {
                logger.error("Redis实例初始化失败 | 实例键：{}，配置：{}，异常：{}",
                        instanceKey, config, e.getMessage(), e);
            }
        }
    }

    /**
     * 根据实例键获取Redis客户端（不存在时返回null）
     */
    public Redis getRedis(String instanceKey) {
        return redisInstances.get(instanceKey);
    }

    /**
     * 关闭所有Redis实例（释放资源）
     */
    public void shutdown() {
        for (Map.Entry<String, Redis> entry : redisInstances.entrySet()) {
            String instanceKey = entry.getKey();
            Redis redis = entry.getValue();
            try {
                redis.close();
                logger.info("Redis实例已关闭 | 实例键：{}", instanceKey);
            } catch (Exception e) {
                logger.error("Redis实例关闭失败 | 实例键：{}，异常：{}", instanceKey, e.getMessage(), e);
            }
        }
        redisInstances.clear();
    }

    /**
     * 配置校验
     */
    private void validateConfig(RedisConfig config) {
        if (StrUtil.isBlank(config.getHost())) {
            throw new InvalidConfigException("Redis主机地址不能为空");
        }
        if (config.getPort() < 0 || config.getPort() > 65535) {
            throw new InvalidConfigException("Redis端口必须在0-65535之间，当前值：" + config.getPort());
        }
        if (config.getDb() < 0 || config.getDb() > 15) {
            throw new InvalidConfigException("Redis数据库索引必须在0-15之间，当前值：" + config.getDb());
        }
    }

    private enum Singleton {
        INSTANCE;

        private final RedisMgr manager;

        Singleton() {
            this.manager = new RedisMgr();
        }

        public RedisMgr getManager() {
            return manager;
        }
    }
}